#! /bin/sh
#
# Wrapper that invokes xsltproc on the junos-xsd2yang.xsl script
#
progname="`basename $0`"


JXSD2YANG_XSL=./junos-xsd2yang.xsl


saxon_jar="/usr/share/java/saxon.jar"
java="java"
file="-"
args=""
products=""


usage() {
    cat <<EOF
Usage:

  $progname [options] [-o <outputfile>] [<filename>]

Converts a JunOS XML schema file to YANG. By default the schema file is read
from stdin, and the resulting YANG module written to stdout. (Use -o option
to give alternate output file, and supply filename as argument to indicate
source file). Other options are:

  --product <name>        Filter the schema file to only include support for
                          product <name>. (Multiple --product can be given,
                          the resulting YANG file will be the union of all
                          products listed. For example:

                            $progname --product mx80 --product mx240

  --tailf-extensions      Use (default) or don't use tailf extensions to work
  --no-tailf-extensions   around specific issues in translating the JunOS
                          XML schema to YANG.

  --apply-groups          Enable (default), or disable generating a YANG model
  --no-apply-groups       that supports JunOS "group" / "apply-groups" feature.

The resulting YANG module is not indented properly, to pretty-print it use for
example "pyang -f yang".

The translation is implemented using XSLT, so an XSLT processor is
required. The script works with both xsltproc and Saxon (which is
*significantly* faster than xsltproc). By default the script looks for
the Saxon jar file in ${saxon_jar}, or you can explicitly
point out the jar file using the SAXON_JAR environment variable or the
--saxon option. The Java runtime binary 'java' must be in \$PATH (or
the complete path to it can be set using the --java option). If the
Saxon jar can not be found, the fallback is to use xsltproc (which
must be in \$PATH).

Getting the JunOS schema: The schema can be obtained from any JunOS
router with NETCONF enabled using the get-xnm-information NETCONF rpc:

  <rpc>
    <get-xnm-information>
      <type>xml-schema</type>
      <namespace>junos-configuration</namespace> 
    </get-xnm-information>
  </rpc>

This script includes support for issuing this rpc using ssh, by
invoking it like this:

  $progname --get-schema [-l <username>] <remote-address>

You will be prompted by ssh for the password (unless you are using ssh keys).

EXAMPLES

  > $progname --get-schema -l admin -o /tmp/junos.xsd 192.168.1.96
  Fetching JunOS schema from: 192.168.1.96, saving in /tmp/junos.xsd...

  > $progname --product m10 -o /tmp/junos.yang /tmp/junos.xsd

Using Saxon (installed somewhere else) as the XSLT processor:

  > $progname --saxon /usr/local/share/saxon6-5-5/saxon.jar -o /tmp/junos.yang /tmp/junos.xsd

Using pyang to pretty-print:

  > $progname /tmp/junos.xsd | pyang -f yang -o /tmp/junos.yang

EOF
}

while [ $# -gt 0 ]; do
    case "$1" in
	--product)
	    products="$products $2 "
	    shift
	    ;;
	--apply-groups)
	    args="$args --param gApplyGroups true() "
	    saxon_args="$saxon_args gApplyGroups=true() "
	    ;;
	--no-apply-groups)
	    args="$args --param gApplyGroups false() "
	    saxon_args="$saxon_args gApplyGroups=false() "
	    ;;
	--tailf-extensions)
	    args="$args --param gTailfExt true()"
	    saxon_args="$saxon_args gTailfExt=true() "
	    ;;
	--no-tailf-extensions)
	    args="$args --param gTailfExt false()"
	    saxon_args="$saxon_args gTailfExt=false() "
	    ;;
	--dyncamic-profiles)
	    args="$args --param gDynamicProfiles true() "
	    saxon_args="$saxon_args gDynamicProfiles=true() "
	    ;;
	--no-dyncamic-profiles)
	    args="$args --param gDynamicProfiles false() "
	    saxon_args="$saxon_args gDynamicProfiles=false() "
	    ;;
	-h|--help|-\?)
	    usage
	    exit 0
	    ;;
	-o)
	    output="$2"
	    shift
	    ;;
	--saxon)
	    saxon_jar="$2"
	    shift
	    ;;
	--java)
	    java="$2"
	    shift
	    ;;
	--get-schema)
	    mode=get-schema
	    ;;
	-l)
	    ruser="$2"
	    shift
	    ;;
	-*)
	    echo "$progname: Unknown option: $1 (use -h to get usage info)"
	    exit 1
	    ;;
	*)
	    if [ x"$file" != "x-" ]; then
		echo "$progname: Only supply one input file (use -h to get usage info)"
		exit 1
	    fi
	    file="$1"
	    ;;
    esac
    shift
done

if [ x"$mode" = xget-schema ]; then
    if [ x"$output" = x ]; then
	output="./junos.xsd"
    fi
    if [ x"$file" = "x-" ]; then
	echo "Need remote host as argument!"
	exit 1
    fi
    if [ x"$ruser" != x ]; then
	ruser="-l $ruser"
    fi
    echo "Fetching JunOS schema from: ${file}, saving in ${output}..."
    ssh $ruser -s $file netconf <<EOF | awk 'BEGIN{p=0}/<xsd:schema/{p=1}p{print;}/<\/xsd:schema/{p=0;}' > "$output"
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capabilities>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
  </capabilities>
</hello>
]]>]]>
<rpc>
  <get-xnm-information>
    <type>xml-schema</type>
    <namespace>junos-configuration</namespace> 
  </get-xnm-information>
</rpc>
]]>]]>
<rpc>
  <close-session/>
</rpc>
]]>]]>
EOF
    exit $?
fi

if [ x"$output" = x ]; then
    out=""
else
    out="-o $output"
fi

if [ ! -e "$saxon_jar" ]; then
    if [ x"$SAXON_JAR" != x ] && [ -e "$SAXON_JAR" ]; then
	saxon_jar="$SAXON_JAR"
    else
	saxon_jar=""
    fi
fi

if [ x"$saxon_jar" = x ]; then

    exec xsltproc $args $out --param product-filter "'$products'" \
	"${JXSD2YANG_XSL}" "${file}"

else

    CLASSPATH=${saxon_jar}:${CLASSPATH}
    export CLASSPATH
    # Silly Saxon doesn't allow empty string as a parameter value from cmdline
    if [ x"${products}" = x ]; then
	exec "${java}" com.icl.saxon.StyleSheet $out "${file}" \
	    "${JXSD2YANG_XSL}" ${saxon_args}
    else
	exec "${java}" com.icl.saxon.StyleSheet $out "${file}" \
	    "${JXSD2YANG_XSL}" product-filter="$products" ${saxon_args}
    fi

fi
